from random import shuffle

ALL_BUFF = ['力量', '敏捷', '虚弱', '脆弱', '易伤', '仪式']
TRIGGER = {
    'before_turn': [],  # 回合开始前
    'draw_card': [],  # 抽牌时
    'play_card': [],  # 出牌时
    'exhaust_card': [],  # 消耗牌时
    'drop_card': [],  # 弃牌时
    'turn_over': [],  # 回合结束时
    'monster_action_before': [],  # 怪物回合开始时
    'monster_action': [],  # 怪物行动
    'monster_action_down': [],  # 怪物行动结束
}


class Monster:
    """
    杀戮尖塔怪物mod
    """

    def __init__(self, name, max_hp):
        self.max_hp = max_hp
        self.name = name
        self.buffer = [0 for i in range(10)]
        self.attack_num = 1
        self.base_damage = 0
        self.defend = 0
        self.hp = max_hp

    def action(self, *args, **kwargs):
        pass

    def attack(self, player):
        damage = self.base_damage + self.buffer[0]
        for i in range(self.attack_num):
            # 如果有脆弱buff，伤害减25%
            if self.buffer[3] > 0:
                damage = int(damage * 0.75)
            # 如果有易伤buff，伤害加50%
            if player.buffer[4] > 0:
                damage = int(damage * 1.5)
            # damage 小于 格挡值
            if damage < player.defend:
                player.defend -= damage
            else:
                player.hp -= (damage - player.defend)
                player.defend = 0

    def reset(self):
        self.buffer = [0 for i in range(20)]
        self.attack_num = 1
        self.base_damage = 0
        self.defend = 0
        self.hp = self.max_hp


class Player:
    """
    杀戮尖塔玩家mod
    """

    def __init__(self, max_hp, max_mp):
        self.max_hp = max_hp
        self.max_mp = max_mp
        self.mp = max_mp
        self.hp = max_hp
        self.defend = 0
        self.buffer = [0 for i in range(10)]
        self.hand_card = [0 for i in range(10)]
        self.draw_deck = [0 for i in range(30)]
        self.drop_deck = [0 for i in range(30)]
        self.exhaust_deck = [0 for i in range(30)]
        self.draw_num = 5

    def reset(self):
        self.buffer = [0 for i in range(20)]
        self.hand_card = [0 for i in range(10)]
        self.draw_deck = [0 for i in range(30)]
        self.drop_deck = [0 for i in range(30)]
        self.exhaust_deck = [0 for i in range(120)]
        self.draw_num = 5
        self.mp = self.max_mp
        self.hp = self.max_hp
        self.defend = 0

    def play_card(self, card_no, cards, monster, game):
        if card_no == 10:
            return 0
        card_id = self.hand_card[card_no]
        if card_id == 0:
            return -0.1
        card = cards.get(card_id)  # 取出来为一个Card实例
        if card.cost > self.mp:
            return -0.1
        card.use(monster, self, game)
        self.hand_card[card_no] = 0
        # 整理手牌
        hand_card = list(filter(lambda x: x != 0, self.hand_card))
        self.hand_card[:len(hand_card)] = hand_card
        self.hand_card[len(hand_card):] = [0 for i in range(10 - len(hand_card))]
        # 将打出的牌放入弃牌堆
        drop_deck = list(filter(lambda x: x != 0, self.drop_deck))
        drop_deck.append(card_id)
        self.drop_deck[:len(drop_deck)] = drop_deck
        self.drop_deck[len(drop_deck):] = [0 for i in range(30 - len(drop_deck))]
        return 0.1

    def draw_card(self, *args, **kwargs):
        for i in range(self.draw_num):
            can_draw = self.draw_one_card()
            if not can_draw:
                break

    def draw_one_card(self, *args, **kwargs):
        # 获取抽牌堆长度
        draw_deck = list(filter(lambda x: x != 0, self.draw_deck))
        draw_deck_len = len(draw_deck)
        # 获取手牌长度
        hand_card = list(filter(lambda x: x != 0, self.hand_card))
        hand_card_len = len(hand_card)
        # 获取弃牌堆长度
        drop_deck = list(filter(lambda x: x != 0, self.drop_deck))
        drop_deck_len = len(drop_deck)
        # 如果抽牌堆为空，并且弃牌堆为空, 跳过这次抽牌
        if draw_deck_len == 0 and drop_deck_len == 0:
            return False
        # 如果抽牌堆为空，将弃牌堆洗牌后放入抽牌堆
        if draw_deck_len == 0:
            # 洗牌 drop_deck打乱顺序
            shuffle(drop_deck)
            self.drop_deck[:drop_deck_len] = drop_deck
            self.drop_deck[drop_deck_len:] = [0 for i in range(30 - drop_deck_len)]
            self.draw_deck = self.drop_deck
            self.drop_deck = [0 for i in range(30)]
        # 取出抽牌堆第一张牌
        card_id = self.draw_deck[0]
        # 抽牌堆前移一位
        self.draw_deck = self.draw_deck[1:]
        # 抽牌堆最后一位补0
        self.draw_deck.append(0)
        # 如果手牌满了，将抽到的牌放入弃牌堆
        if hand_card_len == 10:
            drop_deck = list(filter(lambda x: x != 0, self.drop_deck))
            drop_deck.append(card_id)
            self.drop_deck[:len(drop_deck)] = drop_deck
            self.drop_deck[len(drop_deck):] = [0 for i in range(30 - len(drop_deck))]
        else:
            # 否则放入手牌
            hand_card = list(filter(lambda x: x != 0, self.hand_card))
            hand_card.append(card_id)
            self.hand_card[:len(hand_card)] = hand_card
            self.hand_card[len(hand_card):] = [0 for i in range(10 - len(hand_card))]
        return True

    def drop_card(self, *args, **kwargs):
        # 将手牌中的牌放入弃牌堆
        drop_deck = list(filter(lambda x: x != 0, self.drop_deck))
        hand_card = list(filter(lambda x: x != 0, self.hand_card))
        drop_deck.extend(hand_card)
        self.drop_deck[:len(drop_deck)] = drop_deck
        self.drop_deck[len(drop_deck):] = [0 for i in range(30 - len(drop_deck))]
        self.hand_card = [0 for i in range(10)]


class Card:
    """
    杀戮尖塔卡牌mod
    """

    def __init__(self, id, name, cost, description, type):
        self.id = id
        self.cost = cost
        self.name = name
        self.description = description
        self.type = type

    def use(self, monster, player, game):
        pass

    def attack(self, damage, monster, player):
        damage = damage + player.buffer[0]
        # 如果有脆弱buff，伤害减25%
        if player.buffer[3] > 0:
            damage = int(damage * 0.75)
        # 如果有易伤buff，伤害加50%
        if monster.buffer[4] > 0:
            damage = int(damage * 1.5)
        # damage 小于 格挡值
        if damage < monster.defend:
            monster.defend -= damage
        else:
            monster.hp -= (damage - monster.defend)
            player.defend = 0

    def defend(self, defend, player):
        player.defend += defend + player.buffer[1]
